[Scala]01 Scala学习笔记

scala 的下载安装、scala初体验[编译运行]、Scala入门[Scala 数据类型、lazy在Scala中的使用]、函数的定义和使用[条件表达式、循环表达式]、Scala对象[类的定义和使用、主构造器和附属构造器以及继承、抽象类、伴生类和伴生对象、cass class、Trait]、Scala 集合[数组、List、Map、Option&Some&None、Tuple]

Posted by 李玉坤 on 2018-03-10

scala 的下载安装

前置条件需要安装JDK8

1
2
3
4
[hadoop@hadoop app]$ java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)

官网下载:https://downloads.lightbend.com/scala/2.12.11/scala-2.12.11.tgz

1、解压: tar -zxvf scala-2.12.11.tgz -C ../app/
2、加上软连接:ln -s scala-2.12.11/ scala
3、配置环境变量

1
2
3
4
5
6
7
8
9
进入环境变量
vim ~/.bash_profile

添加
export SCALA_HOME=/home/hadoop/app/scala
export PATH=$SCALA_HOME/bin:$PATH

刷新环境变量
source ~/.bash_profile

scala初体验

小试牛刀

1
2
3
4
5
6
7
8
9
10
11
scala> 1+2
res0: Int = 3

scala> res0 * 3
res1: Int = 9

scala> res0 * res1
res2: Int = 27

scala> println("Hello World")
Hello World

编译运行

vim HelloWorld.scala

1
2
3
4
5
object HelloWorld{
def main(args: Array[String]){
println("Hello World...")
}
}

编译:scalac HelloWorld.scala
运行:scala HelloWorld
结果:Hello World…

Scala入门

val vs var

val:值
final
val 值名称:类型 = XXX
var:变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scala> val money = 100
money: Int = 100

scala> money = 200
<console>:12: error: reassignment to val
money = 200
^
scala> val age:Int = 20
age: Int = 20

scala> var name:String = "zs"
name: String = zs

scala> name = "ls"
name: String = ls

建议:优先使用val

Scala 数据类型

Byte/Char
Short/Int/Long/Float/Double
Boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
scala> val a:Int = 10
a: Int = 10

scala> val b:Boolean = true
b: Boolean = true

scala> val c = false
c: Boolean = false

scala> val d = 1.1
d: Double = 1.1

scala> val e:Float = 1.1
<console>:11: error: type mismatch;
found : Double(1.1)
required: Float
val e:Float = 1.1
^

scala> val e:Float = 1.1f
e: Float = 1.1

scala> val d = 1.1f
d: Float = 1.1

scala> val f = 10
f: Int = 10

类型转换
scala> val g = 10.asInstanceOf[Double]
g: Double = 10.0

类型判断
scala> val h = 10.isInstanceOf[Int]
h: Boolean = true

lazy在Scala中的使用

1
2
3
4
5
scala> lazy val a = 1
a: Int = <lazy>

scala> a
res0: Int = 1

比如当读取一个文件a的时候,讲文件赋值给lazy 变量a,只有当调用的时候才会返回文件内容

函数的定义和使用[条件表达式、循环表达式]

1
2
3
4
5
6
def 方法名(参数名:参数类型): 返回值类型 = {
// 括号内的叫做方法体


// 方法体内的最后一行为返回值,不需要使用return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
object FunctionApp {

def main(args: Array[String]): Unit = {


// println(add(2, 3))
//
// println(three())
// println(three) // 没有入参的函数,调用时括号是可以省略的

无参与有参调用
// sayHello()
// sayHello
// sayHello("zhangsan")

默认参数的调用
// sayName() //默认参数的调用
// sayName("zhangsan")
//
// loadConf()
// loadConf("spark-production.conf") //默认参数的调用

命名参数调用
// println(speed(100, 10)) //顺序传参
// println(speed(distance = 100, time = 10))
// println(speed(time = 10, distance = 100)) //无顺序传参

可变参数的调用
// println(sum(1,3,5))
// println(sum2(1,2)) //不确定传参个数
// println(sum2(1,2,3))
// println(sum2(1,2,3,4))

条件表达式
// val x = 1
// if(x > 0) {
// true
// } else {
// false
// }

循环表达式to
// 1 to 10 左闭右闭
// 1.to(10) 左闭右闭
// Range(1,10,4) //1 5 9
// 1.until(10) 左闭右开

循环表达式for
// for(i <- 1 to 10 if i % 2 == 0) {
// println(i)
// }

循环表达式for
// val courses = Array("Hadoop","Spark SQL", "Spark Streaming","Storm","Scala")
// for(course <- courses) {
// println(course)
// }

// course 其实就是courses里面的每个元素
// ==> 就是将左边的course作用上一个函数,变成另外一个结果
// println 就是作用到course上的一个函数
// courses.foreach(course => println(course))

循环表达式while
var (num, sum) = (100, 0)
while(num > 0) { // 出口
sum = sum + num
num = num - 1 // 步长
}
println(sum)

}


def add(x:Int, y:Int):Int = {
x + y // 最后一行就是返回值,不需要return
}

def three() = 1 + 2

def sayHello(): Unit = {
println("Say hello....")
}

def sayHello(name:String): Unit = {
println("Say hello: " + name)
}

def sayName(name:String = "lisi"): Unit = {
println(name)
}

def loadConf(conf:String = "spark-defaults.conf"): Unit = {
println(conf)
}

def speed(distance:Float, time:Float):Float = {
distance/time
}


def sum(a:Int, b:Int) = {
a + b
}

def sum(a:Int, b:Int, c:Int) = {
a + b + c
}

def sum2(numbers:Int*) = {

var result = 0
for(number <- numbers) {
result += number
}

result
}


}

Scala对象

面向对象

Java/Scala OO
封装:属性、方法封装到类中
Person:
private int id, String name, Date birthday….. getter/setter
eat、sleep….
继承:父类和子类之间的关系
User extends Person
exam…..
多态:***** 父类引用指向子类对象 精髓所在 开发框架的基石
Person person = new Person();
User user = new User();
Person person = new User();

类的定义和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
object SimpleObjectApp {

def main(args: Array[String]): Unit = {
val person = new People()
person.name = "Messi"
// person.age = 30 val不可改变
println(person.name + " .. " + person.age)

println("invoke eat method: " + person.eat)

person.watchFootball("Barcelona")


person.printInfo()
// println(person.gender) 不可以直接访问类里的this修饰属性
}

}

//People类
class People {

// 定义属性
var name:String = _ //占位符
val age = 10


private [this] val gender = "male"

def printInfo(): Unit ={
println("gender: " + gender)
}

// 定义方法
def eat():String = {
name + " eat...."
}

def watchFootball(teamName: String): Unit = {
println(name + " is watching match of " + teamName)
}
}

主构造器和附属构造器以及继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
object ConstructorApp {
def main(args: Array[String]): Unit = {

// val person = new Person("zhangsan", 30)
// println(person.name + " : " + person.age + " : " + person.school)
//
//
// val person2 = new Person("PK", 18, "M")
// println(person2.name + " : "
// + person2.age + " : "
// + person2.school + " :"
// + person2.gender
// )

val student = new Student("PK", 18, "Math")
println(student.name + " : " + student.major)

println(student)

}

}


// 主构造器
class Person(val name:String, val age:Int) {
println("Person Constructor enter....")


val school = "ustc"
var gender:String = _

// 附属构造器
def this(name:String, age:Int, gender:String) {
this(name, age) // 附属构造器的第一行代码必须要调用主构造器或者其他附属构造器
this.gender = gender
}

println("Person Constructor leave....")
}

// 继承
class Student(name:String, age:Int, var major:String) extends Person(name, age) {
println("Person Student enter....")

//重写
override val school = "peking"
//重写
override def toString: String = "Person: override def toString :" + school

println("Person Student leave....")
}

抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
object AbstractApp {

def main(args: Array[String]): Unit = {


val student = new Student2()
println(student.name)
student.speak
}

}


/**
* 类的一个或者多个方法没有完整的实现(只有定义,没有实现)
*/
abstract class Person2 {

def speak

val name:String
val age:Int

}


class Student2 extends Person2 {
override def speak: Unit = {
println("speak")
}

override val name: String = "zhangsan"
override val age: Int = 18
}

伴生类和伴生对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
object ApplyApp {

def main(args: Array[String]): Unit = {
// for(i <- 1 to 10) {
// ApplyTest.incr
// }
//
// println(ApplyTest.count) // 10 说明object本身就是一个单例对象

val b = ApplyTest() // ==> 调用的是Object.apply

println("~~~~~~~~~~~")
val c = new ApplyTest() // 调用的是class.apply
println(c) // 调用的是class.apply
c() // 调用的是class.apply

// 类名() ==> 调用 Object.apply
// 对象() ==> 调用 Class.apply

}

}

/**
* 伴生类和伴生对象
* 如果有一个class,还有一个与class同名的object
* 那么就称这个object是class的伴生对象,class是object的伴生类
*/

class ApplyTest{
def apply() = {
println("class ApplyTest apply....")
}
}

object ApplyTest{

println("Object ApplyTest enter....")

var count = 0

def incr = {
count = count + 1
}

// 最佳实践:在Object的apply方法中去new Class
def apply():ApplyTest = {
println("Object ApplyTest apply....")

// 在object中的apply中new class
new ApplyTest
}


println("Object ApplyTest leave....")

}

cass class

1
2
3
4
5
6
7
8
9
10
11
// 通常用在模式匹配
object CaseClassApp {

def main(args: Array[String]): Unit = {
println(Dog("wangcai").name)
}

}

// case class不用new
case class Dog(name:String)

Trait

多继承

1
2
3
4
5
6
7
8
9
10
Trait   xxx extends ATrait with BTrait
class SparkConf(loadDefaults: Boolean)
extends Cloneable
with Logging
with Serializable
...
....
traint Cloneable [extends XXX] {}
traint Logging {}
traint Serializable {}

Scala 集合

immutable 不可变
mutable 可变

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
object ArrayApp extends App{


// val a = new Array[String](5) 长度为5的空数组
// a.length
// a(1) = "hello" 给a[1]赋值
// a(1) 取值
//
// val b = Array("hadoop", "spark", "storm")
//
// val c = Array(2,3,4,5,6,7,8,9)
// c.sum
// c.min
// c.max
//
// c.mkString(",") 去掉分隔符 转换为了string类型
c.mkString("and") // 2and3and4and5and6and7and8and9
c.mkString("<",",",">") // <2,3,4,5,6,7,8,9>

//可变数组
val c = scala.collection.mutable.ArrayBuffer[Int]()

c += 1
c += 2
c += (3,4,5)
c ++= Array(6,7,8)
c.insert(0,0) //在0位置添加0
c.remove(1)
c.remove(0,3)
c.trimEnd(2) //从尾巴开始删除
c.toArray 可变数组变为不可变数组

数组取数
// for(i <- 0 until c.length) {
// println(c(i))
// }

数组取数
// for(ele <- c) {
// println(ele)
// }

数组反向取数
for(i <- (0 until c.length).reverse) {
println(c(i))
}


// println(c.toArray.mkString)


}

List

面试点:Nil 空的集合
scala> Nil
res1: scala.collection.immutable.Nil.type = List()
scala> val l = List(1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)

scala> l.head
res2: Int = 1

scala> l.tail
res3: List[Int] = List(2, 3, 4, 5)

scala> val l2 = 1 :: Nil
l2: List[Int] = List(1)

scala> val l3 = 2 :: l2
l3: List[Int] = List(2, 1)

scala> val l4 = 1 :: 2 :: 3 :: Nil
l4: List[Int] = List(1, 2, 3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
object ListApp extends App{


// val l = List(1,2,3,4,5)
//
//
// val l5 = scala.collection.mutable.ListBuffer[Int]() 变长List

添加数值
// l5 += 2
// l5 += (3,4,5)
// l5 ++= List(6,7,8,9)
//
删除数值
// l5 -= 2
// l5 -= 3
// l5 -= (1, 4)
// l5 --= List(5,6,7,8)
//
// println(l5)
//
//
// l5.isEmpty 判断是否为空
// l5.head 取第一个
// l.tail 取除了第一个的值 2,3,4,5



def sum(nums:Int*):Int = {
if(nums.length == 0) {
0
} else {
nums.head + sum(nums.tail:_*) //:_*将seq转为一个可变参数
}
}

println(sum())
println(sum(1,2,3,4))

无序不可重复
// val set = scala.collection.mutable.Set[Int]()
// set += 1
// set += (1,1)
scala> val set = scala.collection.mutable.Set[Int]()
set: scala.collection.mutable.Set[Int] = Set()

scala> set += 1
res6: set.type = Set(1)

scala> set += (1,1)
res7: set.type = Set(1)

scala> set += (2,1)
res8: set.type = Set(1, 2)

scala> set += (1,1)
res9: set.type = Set(1, 2)

}

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import scala.collection.mutable
import scala.collection.mutable._
object MapApp extends App{



val a = Map("lisi" -> 18, "zhangsan" -> 30)

val b = Map("lisi" -> 18, "zhangsan" -> 30)

// val c = mutable.HashMap[String,Int]()
// b.getOrElse("lisi", 9) 取lisi的value 没有就输出9

循环遍历map
// for((key,value) <- b) {
// println(key + " : " + value )
// }

循环遍历map
// for(key <- b.keySet) {
// println(key + " : " + b.getOrElse(key, 9))
// }

循环遍历map中的value
// for(value <- b.values) {
// println(value)
// }

循环遍历map
for((key,_) <- b) {
println(key + " : " + b.getOrElse(key, 9) )
}

}

Option&Some&None

1
2
3
4
5
scala> val a = Map("lisi" -> 18, "zhangsan" -> 30)
a: scala.collection.immutable.Map[String,Int] = Map(lisi -> 18, zhangsan -> 30)

scala> a.get("lisi")
res10: Option[Int] = Some(18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
object OptionApp extends App {


val m = Map(1 -> 2)
// println(m(1))
// println(m(2))

// println(m.get(1).get)

println(m.getOrElse(2, "None"))
}


/**
* case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}

final case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}

*/

Tuple

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.imooc.scala.course05

// 元组:(.......)
object TupleApp extends App{

val a = (1,2,3,4,5)

遍历元组
for(i <- 0 until(a.productArity)) {
println(a.productElement(i))
}

val hostPort = ("localhost",8080)
hostPort._1
hostPort._2

}